/*
 * Copyright 2003-2005 (c) Live Media Pty Ltd. <argot@einet.com.au> 
 *
 * This software is licensed under the Argot Public License 
 * which may be found in the file LICENSE distributed 
 * with this software.
 *
 * More information about this license can be found at
 * http://www.einet.com.au/License
 * 
 * The Developer of this software is Live Media Pty Ltd,
 * PO Box 4591, Melbourne 3001, Australia.  The license is subject 
 * to the law of Victoria, Australia, and subject to exclusive 
 * jurisdiction of the Victorian courts.
 */

using System;

using TypeElement = argot.TypeElement;
using TypeException = argot.TypeException;
using TypeInputStream = argot.TypeInputStream;
using TypeOutputStream = argot.TypeOutputStream;
using TypeReader = argot.TypeReader;
using TypeWriter = argot.TypeWriter;

namespace argot.common
{
	
	/// <summary> 
	/// This is a basic 32-bit unsigned int value stored in big endian format,
	/// </summary>
	public class BigEndianUnsignedInteger 
	:TypeReader, TypeWriter
	{
		
		public const System.String TYPENAME = "u32";

		public unsafe virtual System.Object Read(TypeInputStream inStream, TypeElement element)
		{
			byte[] array = new byte[4];
			
			if ( inStream.Stream.Read( array,0,4 ) < 4 )
				throw new System.IO.EndOfStreamException();

			if ( BitConverter.IsLittleEndian )
			{
				byte b = array[0]; array[0] = array[3]; array[3] = b;
				b = array[1]; array[1] = array[2]; array[2] = b;
			}

			fixed( byte* parray = array )
			{
				return *((System.UInt32 *)parray);
			}
		}
		
		public virtual void Write(TypeOutputStream outStream, System.Object o, TypeElement element)
		{
			int a, b, c, d;
			
			if (!(o is System.Int64))
				throw new TypeException("U32B: requires Long");
			
			long s = (long) ((System.Int64) o);
			
			if (s < MIN || s > MAX)
				throw new TypeException("U16B: value out of range:" + s + " " + MAX);
			
			a = (int) (s & (long) 0xff000000) >> 24;
			b = (int) (s & 0x00ff0000) >> 16;
			c = (int) (s & 0x0000ff00) >> 8;
			d = (int) (s & 0x000000ff);
			
			outStream.Stream.WriteByte((System.Byte) a);
			outStream.Stream.WriteByte((System.Byte) b);
			outStream.Stream.WriteByte((System.Byte) c);
			outStream.Stream.WriteByte((System.Byte) d);
		}
		
		public const long MIN = 0;
		
		// max value is 2^16 x 2^16..  just as easy way to write it.
		//UPGRADE_NOTE: Final was removed from the declaration of 'MAX '. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1003"'
		public const long MAX = (long) (65536L * 65536L); //2^32-1;
	}
}